package com.lwl.leetcode.滑动窗口;

import java.util.LinkedList;

/**
 * @author lwl
 * @Description 1438. 绝对差不超过限制的最长连续子数组
 * 中等
 * 相关标签
 * conpanies icon
 * 相关企业
 * 提示
 * 给你一个整数数组 nums ，和一个表示限制的整数 limit，请你返回最长连续子数组的长度，该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit。
 * 示例 1：
 * 输入：nums = [8,2,4,7], limit = 4
 * 输出：2
 * 解释：所有子数组如下：
 * [8] 最大绝对差 |8-8| = 0 <= 4.
 * [8,2] 最大绝对差 |8-2| = 6 > 4.
 * [8,2,4] 最大绝对差 |8-2| = 6 > 4.
 * [8,2,4,7] 最大绝对差 |8-2| = 6 > 4.
 * [2] 最大绝对差 |2-2| = 0 <= 4.
 * [2,4] 最大绝对差 |2-4| = 2 <= 4.
 * [2,4,7] 最大绝对差 |2-7| = 5 > 4.
 * [4] 最大绝对差 |4-4| = 0 <= 4.
 * [4,7] 最大绝对差 |4-7| = 3 <= 4.
 * [7] 最大绝对差 |7-7| = 0 <= 4.
 * 因此，满足题意的最长子数组的长度为 2 。
 * @date 2025/9/1 14:48
 */
public class Code1438LongestSubarray {
    public static void main(String[] args) {
        int[] nums = {1, 5, 6, 7, 8, 10, 6, 5, 6};
        int limit = 4;
        System.out.println(longestSubarray(nums, limit));
    }

    public static int longestSubarray(int[] nums, int limit) {
        int l = 0;
        int r = 0;
        LinkedList<Integer> maxQueue = new LinkedList<>();
        LinkedList<Integer> minQueue = new LinkedList<>();
        int res = 0;
        while (l < nums.length) {
            while (r < nums.length) {
                // 把 r 放到单调栈中，如果不满足直接 break
                while (!maxQueue.isEmpty() && nums[r] >= nums[maxQueue.peekLast()]) {
                    maxQueue.pollLast();
                }
                maxQueue.addLast(r);
                while (!minQueue.isEmpty() && nums[r] <= nums[minQueue.peekLast()]) {
                    minQueue.pollLast();
                }
                minQueue.addLast(r);
                if (nums[maxQueue.peekFirst()] - nums[minQueue.peekFirst()] > limit) {
                    break;
                }
                r++;
            }
            res = Math.max(res, r - l);
            if (maxQueue.peekFirst() == l) {
                maxQueue.pollFirst();
            }
            if (minQueue.peekFirst() == l) {
                minQueue.pollFirst();
            }
            l++;
        }
        return res;
    }
}
